import string
from typing import List

import numpy as np
from copy import deepcopy
from Env.BaseStations.train import Train

beta_0 = 1
alpha = 2
g = 1
SIGMA_2 = pow(10, -13)  # 高斯白噪声功率 10


# from logger import log

class UAV:
    def __init__(self, id: string, initial_location, env_borders):
        self.e = 10e-27  # 电容系数
        self.connected_user = None
        self.location = None
        self.users_in_range = None
        self.coverage_radius = 100
        self.id = deepcopy(id)
        self.velocity = np.array([0., 0.])
        self.initial_location = initial_location
        self.initial_velocity = deepcopy(self.velocity)
        self.env_borders = env_borders
        self.comp_resource = 1.5e9  # 单位 Hz
        self.bandwidth = 1e7  # 带宽
        self.t_power = 0.5  # 传输功率，单位 W
        self.H = 50
        self.f = 2e9
        self.upload_collision = 0
        self.cache_state = []
        self.trajectory = []
        self.comp_location = 0
        self.trajectory.append(deepcopy(self.location))
        self.users = []
        self.other_uavs: List[UAV] = []
        self.coverage_penalty = []
        self.flight_ec = 0
        self.comp_ec = 0
        self.trans_ec = 0
        # 定义其余需要的属性
        self.P0 = 79.86  # 基础功率，单位瓦特
        self.U_tip = 120  # 旋翼尖速度
        self.Pi = 88.63  # 飞行功率，单位瓦特
        self.rho_0 = 1.225  # 空气密度，单位 kg/m^3
        self.d0 = 0.6  # 机身阻力比
        self.A = 0.503  # 旋翼桨叶面
        self.S = 0.05  # 旋翼密实度
        self.V0 = 4.03  # 悬停状态下的平均旋翼感应速度，单位可以根据实际情况设置（如 m/s）

    def set_other_uavs(self, other_uavs: List['UAV']):
        self.other_uavs = other_uavs

    def collision_occurred(self):
        for other_uav in self.other_uavs:
            distance = np.linalg.norm(self.location - other_uav.location)
            if distance <= 30:
                return True
        return False

    def out_of_border(self):
        """检查前两个坐标 (x, y) 是否超出环境边界，返回布尔值。"""
        # 检查边界条件，记得确保 self.env_borders 是 [[x_min, y_min], [x_max, y_max]]
        x_min, y_min = self.env_borders[0]
        x_max, y_max = self.env_borders[1]

        # 直接返回判断结果
        return (self.location[0] < x_min or self.location[0] > x_max or
                self.location[1] < y_min or self.location[1] > y_max)


    def reset(self):
        self.location = deepcopy(self.initial_location)
        self.velocity = deepcopy(self.initial_velocity)
        self.trajectory = []
        self.trajectory.append(deepcopy(self.location))
        self.cache_state = []
        self.users = []
        self.flight_ec = 0
        self.comp_ec = 0
        self.trans_ec = 0
        return self

    def move(self, angle, velocity, delta_time: np.float64):
        # 计算速度向量
        self.velocity = np.array([np.cos(angle), np.sin(angle), 0]) * velocity
        if self.out_of_border():
            self.velocity = - self.velocity  # 反向
        self.location += self.velocity * delta_time
        self.flight_ec = self.calculate_propulsion_power() * delta_time + 168.49
        self.trajectory.append(self.location.copy())
        return self

    def users_in_coverage_range(self, users):
        self.users_in_range = []
        for user in users:
            # 计算无人机到用户的距离
            distance_to_user = np.linalg.norm(self.location - user.location)
            # 如果用户在无人机的覆盖范围内，则将其添加到列表中
            if distance_to_user <= self.coverage_radius:
                self.users_in_range.append(user)
        return self.users_in_range


    def calculate_propulsion_power(self):
        """计算并更新无人机的推功耗"""
        V = np.linalg.norm(self.velocity)  # 当前速度的范数
        # 根据公式计算推进能耗
        propulsion_energy = (self.P0 * (1 + (3 * V ** 2) / (self.U_tip ** 2)) +
                             self.Pi * np.sqrt(
                    np.sqrt(1 + (V ** 4) / (4 * self.V0 ** 2)) - (V ** 2) / (2 * self.V0 ** 2)) +
                             0.5 * self.d0 * self.A * self.rho_0 * self.S * V ** 3)

        return propulsion_energy  # 计算飞行功耗

    def channel_gain_2(self, node_2_location):
        distance = np.linalg.norm(self.location - node_2_location)
        beta = beta_0 / np.power(distance ** 2, alpha / 2)
        h_2 = beta * g
        return h_2

    def compute_energy(self, computation):
        """计算无人机的计算能耗"""
        return computation * (self.comp_resource ** 2) * self.e

    # def move(self, acceleration, delta_time:np.float64):
    #     """
    #     Diffrent approach can be used to define the kinematic of UAVs
    #     """
    #     # if(self.out_of_battery):
    #     #     return self
    #     # self.battery -= self.power
    #     # if(self.battery < 0):
    #     #     self.out_of_battery = True
    #     acceleration = np.array([acceleration[0], acceleration[1], 0])
    #     self.collision = False

    #     for i in range(len(acceleration)):
    #         if(acceleration[i] > self.max_acceleration[i]):
    #             acceleration[i] = self.max_acceleration[i]
    #         elif(acceleration[i] < -self.max_acceleration[i]):
    #             acceleration[i] = -self.max_acceleration[i]

    #     prev_location = deepcopy(self.location)
    #     self.location += np.multiply(self.velocity, delta_time) + 0.5 * np.multiply(acceleration, delta_time**2)

    #     if(not self.valid_location(self.location)):
    #         if(self.location[0] < self.env_borders[0][0] or self.location[0] > self.env_borders[1][0]):
    #             self.velocity[0] = -self.velocity[0]
    #             self.location = deepcopy(prev_location)
    #         if(self.location[1] < self.env_borders[0][1] or self.location[1] > self.env_borders[1][1]):
    #             self.velocity[1] = -self.velocity[1]
    #             self.location = deepcopy(prev_location)
    #         self.collision = True

    #     self.velocity += np.multiply(acceleration, delta_time)

    #     for i in range(len(self.velocity)):
    #         if(self.velocity[i] > self.max_velocity[i]):
    #             self.velocity[i] = self.max_velocity[i]
    #         elif(self.velocity[i] < -self.max_velocity[i]):
    #             self.velocity[i] = -self.max_velocity[i]

    #     self.trajectory.append(deepcopy(self.location))
    #     return self
